#pragma once

#include "basechart_base.h"

class S_WIDGETS_EXPORT BaseChartVector2D {
 public:
  BaseChartVector2D();
  BaseChartVector2D(double x, double y);
  BaseChartVector2D(const QPoint& point);
  BaseChartVector2D(const QPointF& point);

  // getters:
  double x() const { return mX; }
  double y() const { return mY; }
  double& rx() { return mX; }
  double& ry() { return mY; }

  // setters:
  void setX(double x) { mX = x; }
  void setY(double y) { mY = y; }

  // non-virtual methods:
  double length() const { return qSqrt(mX * mX + mY * mY); }
  double lengthSquared() const { return mX * mX + mY * mY; }
  double angle() const { return qAtan2(mY, mX); }
  QPoint toPoint() const { return QPoint(int(mX), int(mY)); }
  QPointF toPointF() const { return QPointF(mX, mY); }

  bool isNull() const { return qIsNull(mX) && qIsNull(mY); }
  void normalize();
  BaseChartVector2D normalized() const;
  BaseChartVector2D perpendicular() const { return BaseChartVector2D(-mY, mX); }
  double dot(const BaseChartVector2D& vec) const {
    return mX * vec.mX + mY * vec.mY;
  }
  double distanceSquaredToLine(const BaseChartVector2D& start,
                               const BaseChartVector2D& end) const;
  double distanceSquaredToLine(const QLineF& line) const;
  double distanceToStraightLine(const BaseChartVector2D& base,
                                const BaseChartVector2D& direction) const;

  BaseChartVector2D& operator*=(double factor);
  BaseChartVector2D& operator/=(double divisor);
  BaseChartVector2D& operator+=(const BaseChartVector2D& vector);
  BaseChartVector2D& operator-=(const BaseChartVector2D& vector);

 private:
  // property members:
  double mX, mY;

  friend inline const BaseChartVector2D operator*(double factor,
                                                  const BaseChartVector2D& vec);
  friend inline const BaseChartVector2D operator*(const BaseChartVector2D& vec,
                                                  double factor);
  friend inline const BaseChartVector2D operator/(const BaseChartVector2D& vec,
                                                  double divisor);
  friend inline const BaseChartVector2D operator+(
      const BaseChartVector2D& vec1, const BaseChartVector2D& vec2);
  friend inline const BaseChartVector2D operator-(
      const BaseChartVector2D& vec1, const BaseChartVector2D& vec2);
  friend inline const BaseChartVector2D operator-(const BaseChartVector2D& vec);
};

inline const BaseChartVector2D operator*(double factor,
                                         const BaseChartVector2D& vec) {
  return BaseChartVector2D(vec.mX * factor, vec.mY * factor);
}
inline const BaseChartVector2D operator*(const BaseChartVector2D& vec,
                                         double factor) {
  return BaseChartVector2D(vec.mX * factor, vec.mY * factor);
}
inline const BaseChartVector2D operator/(const BaseChartVector2D& vec,
                                         double divisor) {
  return BaseChartVector2D(vec.mX / divisor, vec.mY / divisor);
}
inline const BaseChartVector2D operator+(const BaseChartVector2D& vec1,
                                         const BaseChartVector2D& vec2) {
  return BaseChartVector2D(vec1.mX + vec2.mX, vec1.mY + vec2.mY);
}
inline const BaseChartVector2D operator-(const BaseChartVector2D& vec1,
                                         const BaseChartVector2D& vec2) {
  return BaseChartVector2D(vec1.mX - vec2.mX, vec1.mY - vec2.mY);
}
inline const BaseChartVector2D operator-(const BaseChartVector2D& vec) {
  return BaseChartVector2D(-vec.mX, -vec.mY);
}

/*! \relates BaseChartVector2D

  Prints \a vec in a human readable format to the qDebug output.
*/
inline QDebug operator<<(QDebug d, const BaseChartVector2D& vec) {
  d.nospace() << "BaseChartVector2D(" << vec.x() << ", " << vec.y() << ")";
  return d.space();
}

Q_DECLARE_TYPEINFO(BaseChartVector2D, Q_MOVABLE_TYPE);
